<?php
/**
 * Description:
 *
 * @author      Eden
 * @datetime    2017/2/8 21:47
 * @copyright   WuHan HuQi Technology Co.,Ltd.
 * @url         http://cnhuqi.com
 */

require_once FCPATH . '/application/third_party/wechat/include.php';

use Wechat\Loader;

class Cash_Model extends CI_Model
{
    const CASH_IN_PENDING = 0;
    const CASH_IN_NORMAL = 6;
    const CASH_IN_FAIL = 5;
    const CASH_IN_REMOVE = -1;

    private $error = '';

    private $total = 0;

    private $summary = [];

    /**
     * 初始化
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * 获取充值列表
     * @param $userid
     * @return mixed
     */
    public function getCashInRecord($userid, $offset = 0, $limit = 20)
    {
        $db = clone($this->db);
        $db->where(['userid' => $userid, 'type' => 'cashin']);
        $db->limit($limit, $offset);
        $db->order_by('created', 'DESC');
        $q = $this->get('user_cash_record');
        return $q->result_array();
    }

    public function cashinList($offset, $limit)
    {
        $db = clone ($this->db);

        $db->select('o.id, u.id as userid, u.nickName, o.mealid, m.name, m.amount, o.sn, o.client, o.source, o.created, o.transaction_id');
        $db->where([
            'o.status' => 6
        ]);
        $this->total = $this->getTotal(['status' => 6]);
        $db->order_by('o.created', 'DESC');
        $db->limit($limit, $offset);
        $db->from('user_cashin_order as o');
        $db->join('user as u', 'u.id = o.userid');
        $db->join('cash_meal as m', 'm.id=o.mealid');
        $query = $db->get();
        $rows = $query->result_array();
        if (!empty($rows)) foreach ($rows as &$row) {
            $row['amount_format'] = money_format('%i', $row['amount'] / 100);
        }
        return $rows;
    }

    /**
     * @return int
     */
    public function getTotal()
    {
        return $this->total;
    }

    /**
     * 获取总记录
     * @param $where
     * @return mixed
     */
    public function setTotal($where)
    {
        $db = clone($this->db);
        $db->where($where);
        return $db->count_all_results('user_cashin_order');
    }

    /**
     * @param $userid
     * @param $params
     * @param $client
     * @param $source
     * @return array|bool
     */
    public function order($userid, $params, $client, $source)
    {

        $mealDB = clone($this->db);
        $q = $mealDB->get_where('cash_meal', ['id' => $params['mealId']]);
        $row = $q->row_array();

        if (empty($row)) {
            $this->error = '该套餐不存在';
            return false;
        }

        if ($row['status'] != 6) {
            $this->error = '该套餐不存在';
            return false;
        }

        if ($row['amount'] != $params['amount']) {
            $this->error = '充值金额不符';
            return false;
        }

        $data = array(
            'userid' => $userid,
            'mealid' => $params['mealId'],
            'sn' => sn(),
            'amount' => $row['amount'],
            'client' => $client,
            'source' => $source,
            'created' => dateTime(),
            'updated' => dateTime(),
            'status' => self::CASH_IN_PENDING
        );

        $orderDb = clone($this->db);
        $orderDb->insert('user_cashin_order', $data);
        $id = $orderDb->insert_id();
        if (empty($id)) {
            $this->error = '下单失败';
            return false;
        }

        $data['id'] = $id;
        return $data;
    }

    /**
     * 申请提现
     * @param $user
     * @param int $amount
     * @param string $source
     * @return bool
     */
    public function applyCashout($user, $openid = '', $amount = 0, $source = 'app')
    {
        $userid = $user['id'];

        try {
            $db = clone($this->db);
            $db->trans_start();

            // 总金额不变，amountCashout 增加 amountUnLimit 减少
            $userDb = clone($this->db);
            $userDb->where('id', $userid);
            $userDb->set('amountCashout', "amountCashout+{$amount}", false);
            $userDb->set('amountUnLimit', "amountUnLimit-{$amount}", false);
            $userDb->update('user');

            $applyData = [
                'userId' => $userid,
                'openid' => $openid,
                'amount' => $amount,
                'source' => $source
            ];

            $cashoutDb = clone($this->db);
            $cashoutDb->insert('user_cashout', $applyData);
            $cashoutId = $cashoutDb->insert_id();

            if ($userDb->affected_rows() && $cashoutId) {
                $db->trans_complete();
            }

            return $db->trans_status();

        } catch (Exception $e) {
            $this->error = '申请失败';
        }
        return false;
    }

    /**
     * 取现中
     * @param $userid
     * @return int
     */
    public function getCashoutAmount($userid)
    {
        $results = $this->getCashout($userid, 0);
        $amount = 0;
        if ($results) foreach($results as $ret) {
            $amount += $ret['amount'];
        }
        return $amount;
    }

    /**
     * 充值记录
     * @param $userid
     * @return array
     */
    public function getCashinDetail($userid)
    {
        $where = ['o.userid' => $userid, 'o.status' => 6];
        $db = clone($this->db);
        $db->select('o.id, m.name, m.amount, o.sn, o.client, o.source, o.created');
        $db->from('user_cashin_order as o');
        $db->where($where);
        $db->order_by('created', 'DESC');
        $db->join('cash_meal as m', 'm.id=o.mealid');
        $query = $db->get();
        $rows = $query->result_array();

        $data = [];
        $totalAmount = 0;
        if (!empty($rows)) foreach($rows as $row) {
            $totalAmount += $row['amount'];
            $data[] = [
                'id' => $row['id'],
                'mealName' => $row['name'],
                'amount' => $row['amount'],
                'amount_format' => money_format('%i', $row['amount']/100),
                'sn' => $row['sn'],
                'client' => $row['client'],
                'source' => $row['source'],
                'created' => $row['created'],
                'created_format' => formateTimeStamp($row['created'])
            ];
        }

        $this->summary = [
            'latest' => !empty($data[0]) ? $data[0] : [],
            'total' => $totalAmount
        ];

        return $data;
    }

    /**
     * @return array
     */
    public function getSummary()
    {

        $latest = 0;
        if (!empty($this->summary['latest'])) {
            $latest = $this->summary['latest']['amount'];
        }

        return [
            'total' => money_format('%i', $this->summary['total'] / 100),
            'latest' => money_format('%i', $latest / 100)
        ];
    }

    /**
     * 用户现金记录
     * @param $userid
     * @return array
     */
    public function getCashoutDetail($userid)
    {
        $db = clone($this->db);
        $db->order_by('created', 'DESC');
        /*
        $query = $db->get_where('user_cash_record', [
            'created >=' => date('Y-m-01 00:00:00')
        ]);
        */
        $query = $db->get('user_cash_record');
        $rows = $query->result_array();
        $data = [];
        if (!empty($rows)) foreach ($rows as $row) {
            $moneyFormat = money_format('%i', $row['amount'] / 100);
            $symbol = in_array($row['type'], ['buy', 'cashout']) ? '- ' : '+ ';

            $note = '';
            switch ($row['type']) {
                case "cashin":
                    $note = "用户充值";
                    break;
                case "deduct":
                    $note = "分销提成";
                    break;
                case "cashout":
                    $note = '取现';
                    break;
                case "buy":
                    $note = "购买商品";
                    break;
                case "refund":
                    $note = "退款";
                    break;
            }

            $data[] = [
                'id' => $row['id'],
                'type' => $row['type'],
                'amount' => $row['amount'],
                'amount_format' => $symbol . $moneyFormat,
                'note' => empty($row['note']) ? $note :$row['note'],
                'created' => $row['created'],
                'created_format' => formateTimeStamp($row['created'])
            ];
        }

        return $data;
    }

    /**
     * 提现列表
     * @param $userid
     * @return array
     */
    public function getCashoutApplyList($userid, $status = null)
    {
        $db = clone($this->db);
        $db->order_by('created', 'DESC');
        $where = [];
        $where['userId'] = $userid;
        if ($status !== null) {
            $where['status'] = $status;
        }
        $query = $db->get_where('user_cashout', $where);
        $rows = $query->result_array();
        $data = [];
        if (!empty($rows)) foreach ($rows as $row) {
            $status = '';
            switch ($row['status']) {
                case "0":
                    $status = '审核中';
                    break;
                case "2":
                    $status = '驳回申请';
                    break;
                case "5":
                    $status = '提现失败';
                    break;
                case "6":
                    $status = '提现成功';
                    break;
            }

            $data[] = [
                'id' => $row['id'],
                'amount' => $row['amount'],
                'amount_format' => money_format('%i', $row['amount'] / 100),
                'created' => $row['created'],
                'created_format' => formateTimeStamp($row['created']),
                'source' => $row['source'],
                'status' => $status,
                'note'  => value($row, 'remark')
            ];
        }

        return $data;
    }

    /**
     * 取现列表
     * @param $userid
     * @param int $status
     * @return mixed
     */
    public function getCashout($userid, $status = 0, $limit = 0)
    {
        $db = clone($this->db);
        $db->order_by('created', 'DESC');
        if (!empty($limit)) {
            $db->limit($limit);
        }
        $query = $db->get_where('user_cashout', [
            'userId' => $userid,
            'status' => $status
        ]);

        return $query->result_array();
    }

    /**
     * @return string
     */
    public function getCashError()
    {
        return $this->error = '';
    }

    /**
     * 获取记录
     * @param $userid
     * @param string $type
     * @return array
     */
    public function getRecord($userid, $type = '')
    {
        $db = clone($this->db);
        $db->where('userid', $userid);
        if (!empty($type)) {
            $db->where('type', $type);
        }

        $date = date('Y-m-01 00:00:00');
        $db->where('created >=', $date);
        $db->order_by('created', 'DESC');
        $query = $db->get('user_cash_record');
        $rows = $query->result_array();
        $data = [];
        if (!empty($rows)) foreach ($rows as $item) {
            $money = money_format('%i', $item['amount'] / 100);
            $data[] = [
                'text' => $item['type'] == 'cashin' ? '充值' : '取现',
                'created' => formateTimeStamp($item['created']),
                'type' => $item['type'],
                'amount' => $item['type'] == 'cashin' ? '+ ' . $money : '- ' . $money
            ];
        }
        return $data;
    }

    public function getCashoutLists($status, $offset = 0, $limit = 20)
    {
        $types = [
            'pending' => 0,
            'pass' => 6,
            'reject' => 2,
            'failed' => 5
        ];

        $db = clone($this->db);
        $where = [];
        if ($status != 'all') {
            $where['c.status'] = $types[$status];
        }

        $db->where($where);
        $total = $db->count_all_results('user_cashout as c');
        if ($total == 0) {
            return [
                'total' => 0,
                'data' => []
            ];
        }

        $db->where($where);
        $db->limit($limit, $offset);
        $db->order_by('c.created', 'DESC');
        $db->select('c.id, u.nickName, u.amount as amountLeft, c.userId, c.amount, c.created, c.checked, c.checkedby, c.source, c.status, c.remark');
        $db->join('user as u', 'u.id=c.userId');
        $query = $db->get('user_cashout as c');
        $rows = $query->result_array();

        $adminIds = [];
        if (!empty($rows)) foreach($rows as $item) {
            !empty($item['checkedby']) && $adminIds[] = $item['checkedby'];
        }
        unset($item);

        $this->load->model('common/Admin_Model', 'admin');
        $admins = $this->admin->getAdminsByIds($adminIds);
        foreach($rows as &$item){
            $item['admin'] = value($admins, $item['checkedby'], '');
            $item['amount_cny'] = money_format('%i', $item['amount'] / 100);
            $item['amountLeft_cny'] = money_format('%i', $item['amountLeft'] / 100);
        }

        return [
            'total' => intval($total),
            'data' => $rows
        ];
    }

    /**
     * 通过转账
     * @param $id
     * @return bool
     */
    public function passCashout($id, $return = false)
    {
        $db = clone($this->db);
        try {

            $query = $db->get_where('user_cashout', ['id' => $id]);
            $item = $query->row_array();
            if (empty($item) || $item['status'] != 0){
                return false;
            }

            $adminid = adminId();
            $db->trans_start();

            // 执行转账
            $transferStatus = $this->doTransfer($item['userId'], $item['openid'], $item['amount'], '用户提现');

            // 如果转账成功
            if($transferStatus) {
                // 1. 修改 cashout 表
                $cashoutData = [
                    'status' => 6,
                    'checked' => dateTime(),
                    'checkedby' => adminId()
                ];
                $cashoutDb = clone($this->db);
                $cashoutDb->where('id', $id);
                $cashoutDb->update('user_cashout', $cashoutData);

                // 2. 修改 record 表
                $recordDb = clone($this->db);
                $recordDb->insert('user_cash_record', [
                    'userid' => $item['userId'],
                    'type' => 'cashout',
                    'amount' => $item['amount']
                ]);

                // 修改 user 表
                $userDb = clone($this->db);
                $userDb->where('id', $item['userId']);
                $userDb->set('amount', "amount-{$item['amount']}", false);
                $userDb->set('amountCashout', "amountCashout-{$item['amount']}", false);
                $userDb->update('user');

            }

            // 如果转账失败
            else {
                // 修改 cashout 表
                $cashoutData = [
                    'status' => 5,
                    'checked' => dateTime(),
                    'checkedby' => adminId(),
                    'error' => '转账失败,现金退回用户钱包'
                ];

                $cashoutDb = clone($this->db);
                $cashoutDb->where('id', $id);
                $cashoutDb->update('user_cashout', $cashoutData);

                // 修改 user 表,退钱到账户
                $userDb = clone($this->db);
                $userDb->where('id', $item['userId']);
                $userDb->set('amountUnLimit', "amountUnLimit+{$item['amount']}", false);
                $userDb->set('amountCashout', "amountCashout-{$item['amount']}", false);
                $userDb->update('user');
                unset($userDb);
            }

            $db->trans_complete();
            $res = $db->trans_status();
            if ($res) {
                if ($return) {
                    $this->load->model('common/Admin_Model', 'admin');
                    $admins = $this->admin->getAdminsByIds([$adminid]);
                    $data = $cashoutData;
                    $data['admin'] = $admins[$adminid];

                    return $data;
                }
                return true;
            } else {
                return false;
            }

        } catch(PDOException $e) {
            $this->error = '转账失败';
        }
        return false;
    }

    /**
     * 驳回
     * @param $id
     * @param string $remark
     * @param bool|false $return
     * @return array|bool
     */
    public function rejectCashout($id, $remark = '', $return = false)
    {
        $db = clone($this->db);
        try {
            $adminid = adminId();
            $query = $db->get_where('user_cashout', ['id' => $id]);
            $item = $query->row_array();

            if (empty($item) || $item['status'] != 0) {
                $this->error = '状态错误';
                return false;
            }

            $db->trans_start();
            $rejectData = [
                'status' => 2,
                'remark' => $remark,
                'checked' => dateTime(),
                'checkedby' => $adminid
            ];

            $rejectdb = clone($this->db);
            $rejectdb->where('id', $id);
            $rejectdb->update('user_cashout', $rejectData);

            $userDb = clone($this->db);
            $userDb->where('id', $item['userId']);
            $userDb->set('amountUnLimit', "amountUnLimit+{$item['amount']}", false);
            $userDb->set('amountCashout', "amountCashout-{$item['amount']}", false);
            $userDb->update('user');

            if ($rejectdb->affected_rows() && $userDb->affected_rows()) {
                $db->trans_complete();
            }

            $res = $db->trans_status();
            if ($res) {

                // 模板消息
                /*
                if ($item['source'] == 'wx') {
                    $openid = $item['openid'];
                    $config = $this->config->item('wechat');
                    Loader::config($config);
                    $wechat = Loader::get("receive");
                    $wechat->sendTemplateMessage();
                }
                */

                if ($return) {
                    $this->load->model('common/Admin_Model', 'admin');
                    $admins = $this->admin->getAdminsByIds([$adminid]);
                    $data = $rejectData;
                    $data['admin'] = $admins[$adminid];
                    return $data;
                }
                return $res;
            }
        } catch(Exception $e) {
            $this->error = '驳回错误';
        }
        return false;
    }

    /**
     * 执行转账
     * @return bool
     */
    public function doTransfer($userid, $openid, $amount, $desc = '微信提现')
    {
        $config = $this->config->item('wechat');
        Loader::config($config);
        $pay = Loader::get('pay');

        $sn = sn();
        $createCashoutId = $this->createOrUpdateCashoutWxTransfer([
            'partner_trade_no' => $sn,
            'userid' => $userid,
            'openid' => $openid,
            'amount' => $amount,
            'desc' => $desc,
        ]);

        if (!$createCashoutId) {
            return false;
        }

        $result = $pay->transfers($openid, $amount, $sn, $desc);
        if ($result) {
            if ($result['return_code'] === 'SUCCESS') {
                if ($result['result_code'] === 'SUCCESS') {
                    $update = $result;
                    $update['state'] = 6;
                    return $this->createOrUpdateCashoutWxTransfer($update, $createCashoutId);
                } else {
                    $update = array();
                    $update['err_code'] = isset($result['err_code']) ? $result['err_code'] : '';
                    $update['err_code_des'] = isset($result['err_code_des']) ? $result['err_code_des'] : '';
                    $update['state'] = 5;
                    $this->createOrUpdateCashoutWxTransfer($update, $createCashoutId);
                    return false;
                }
            } else {
                $update = array();
                $update['err_code'] = isset($result['err_code']) ? $result['err_code'] : '';
                $update['err_code_des'] = isset($result['err_code_des']) ? $result['err_code_des'] : '';
                $update['state'] = 5;
                $this->createOrUpdateCashoutWxTransfer($update, $createCashoutId);
                return false;
            }
        } else {
            $update = array();
            $update['err_code'] = $pay->errCode;
            $update['err_code_des'] = $pay->errMsg;
            $update['state'] = 5;
            $this->createOrUpdateCashoutWxTransfer($update, $createCashoutId);
            return false;
        }
    }

    /**
     * @param array $data
     */
    /**
     * 执行转账
     * @return bool
     */
    private function createOrUpdateCashoutWxTransfer(Array $data, $id = 0)
    {
        $save['mch_appid'] = value($data, 'mch_appid', '');    // 可接口返回
        $save['payment_no'] = value($data, 'payment_no', '');   // 接口返回
        $save['payment_time'] = value($data, 'payment_time', '');   // 接口返回
        $save['err_code'] = value($data, 'err_code', '');
        $save['err_code_des'] = value($data, 'err_code_des', '');
        $save['state'] = value($data, 'state', 0);

        $db = clone($this->db);

        if (empty($id)) {
            // 创建
            $save['partner_trade_no'] = value($data, 'partner_trade_no', '');
            $save['userid'] = value($data, 'userid', 0);
            $save['openid'] = value($data, 'openid', '');
            $save['amount'] = value($data, 'amount', 0);
            $save['desc'] = value($data, 'desc', '');
            $save['spbill_create_ip'] = remoteAddr();

            $db->insert('user_cashout_wx', $save);
            return $db->insert_id();
        } else {
            // 修改
            $db->where('id', $id);
            $db->update('user_cashout_wx', $save);
            return $db->affected_rows();
        }
    }

    /**
     * @return string
     */
    public function getError()
    {
        return $this->error;
    }

}
